home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / Xpm / pixmap / ExtEditor.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  18KB  |  656 lines

  1. /*
  2.  * $Id: ExtEditor.c,v 1.4 1992/10/27 08:31:01 mallet Exp $
  3.  *
  4.  * Copyright 1992 Lionel Mallet
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appears in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of Lionel MALLET not be used in
  11.  * advertising or publicity pertaining to distribution of the software
  12.  * without specific, written prior permission.  Lionel MALLET makes no
  13.  * representations about the suitability of this software for any
  14.  * purpose.  It is provided "as is" without express or implied warranty.
  15.  *
  16.  * Lionel MALLET DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  17.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  18.  * FITNESS, IN NO EVENT SHALL Lionel MALLET BE LIABLE FOR ANY SPECIAL,
  19.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  20.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  21.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  22.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23.  *
  24.  *  This software is opened and free. Furthermore, everybody is kindly
  25.  * invited to participate to improve it for the benefit of all.
  26.  * Improvements can be new features, bugs fixes and porting issues
  27.  * resolution.
  28.  *
  29.  * Author:  Tim Wise - Scientific & Engineering Software (SES), Inc.
  30.  */
  31.  
  32.  
  33. /*--------------------------------------------------------------------------*/
  34. /*
  35.                 ExtEditor.c        
  36.  
  37.     This file contains routines used for the xpm extension editor
  38.     of pixmap.
  39.  
  40. */
  41. /*--------------------------------------------------------------------------*/
  42.  
  43. #define NEWLINE '\n'
  44.  
  45. #define min(x, y) (((x) < (y)) ? (x) : (y))
  46. #define max(x, y) (((x) > (y)) ? (x) : (y))
  47.  
  48. extern void unsetKillfromWM();
  49.  
  50. /*--------------------------------------------------------------------------*/
  51. /*
  52.         X p m E x t e n s i o n T o S t r i n g
  53.  
  54.     Convert an xpm extension to a string. Lines of the extension
  55.     are separated by newlines in the string.
  56. */
  57. /*--------------------------------------------------------------------------*/
  58. String XpmExtensionToString( ext )
  59.     XpmExtension *ext;
  60. {
  61.     String s = NULL;
  62.     int    i, len;
  63.  
  64.     if (!ext)
  65.         return NULL;
  66.  
  67.     if (ext->nlines == 0) 
  68.         return "";
  69.  
  70.     for ( i=0, len = 0; i < ext->nlines; i++)
  71.         len += strlen( ext->lines[i] ) + 1; /* plus one for newline or NULL */
  72.  
  73.     s = XtCalloc( len, sizeof(char) );
  74.  
  75.     for ( i=0; i < ext->nlines - 1; i++ ) {
  76.         strcat( s,  ext->lines[i] );
  77.         strcat( s, "\n" );
  78.     }
  79.     strcat( s,  ext->lines[i] );
  80.  
  81.     return s;
  82. }
  83.  
  84.  
  85. /*--------------------------------------------------------------------------*/
  86. /*
  87.         S t r i n g T o X p m E x t e n s i o n
  88.  
  89.     Convert to a string to an xpm extension.  newlines in the
  90.     string cause a new line of the extension to be created.
  91. */
  92. /*--------------------------------------------------------------------------*/
  93. XpmExtension *StringToXpmExtension( s )
  94.     String       s;
  95. {
  96.     XpmExtension *ext;
  97.     String       beg, end;
  98.     int          i, len, n;
  99.  
  100.     if (!s)
  101.         return NULL;
  102.  
  103.     ext  = (XpmExtension *) XtCalloc(1, sizeof(XpmExtension));
  104.  
  105.     /* count nlines (number of newlines + 1) */
  106.     n = 0;
  107.     beg = s;
  108.     for( end=index(beg, NEWLINE); end; end=index(beg, NEWLINE) ) {
  109.         n++; 
  110.         beg = end + 1;
  111.     }
  112.     n++;    
  113.  
  114.     /* assert: n > 0 */
  115.  
  116.     ext->nlines = n; 
  117.     ext->lines  = (char **) XtCalloc(n, sizeof(char *));
  118.  
  119.     /* do newline terminated lines */
  120.     beg = s;
  121.     for ( i=0; i < n - 1; i++ ) {
  122.  
  123.         end = index(beg, NEWLINE);
  124.         len = end - beg;
  125.         ext->lines[i] = (char *) XtCalloc(len + 1, sizeof(char));
  126.  
  127.         strncpy( ext->lines[i], beg, len );
  128.  
  129.         beg = end + 1;
  130.     }
  131.  
  132.     /* last line is null terminated */
  133.     ext->lines[i] = (char *) XtCalloc(strlen(beg) + 1, sizeof(char));
  134.     strcpy( ext->lines[i], beg );
  135.  
  136.     return ext;
  137. }
  138.  
  139.  
  140. /*--------------------------------------------------------------------------*/
  141. /*
  142.             P o s i t i o n P o p u p
  143.  
  144.     Position a popup in the center of its parent. This is the same
  145.     code as is used in Dialog.c/PopupDialog(). 
  146. */
  147. /*--------------------------------------------------------------------------*/
  148. void PositionPopup( popup )
  149.     Widget popup;        /* shell widget to postion */
  150. {
  151.     Widget    parent = XtParent( popup );
  152.  
  153.     Position    parentX, parentY; 
  154.     Dimension    parentWidth, parentHeight;
  155.  
  156.     Position    popupX, popupY;
  157.     Dimension    popupWidth, popupHeight, popupBorder;
  158.  
  159.     Dimension    dpyWidth, dpyHeight;
  160.     Display     *dpy;
  161.  
  162.     int        n;
  163.     Arg        args[4];
  164.  
  165.     n = 0;
  166.     XtSetArg( args[n], XtNx,      &parentX      ); n++;
  167.     XtSetArg( args[n], XtNy,      &parentY      ); n++;
  168.     XtSetArg( args[n], XtNwidth,  &parentWidth  ); n++;
  169.     XtSetArg( args[n], XtNheight, &parentHeight ); n++;
  170.  
  171.     XtGetValues( parent , args, n );
  172.  
  173.     n = 0;
  174.     XtSetArg( args[n], XtNwidth,       &popupWidth  ); n++;
  175.     XtSetArg( args[n], XtNheight,      &popupHeight ); n++;
  176.     XtSetArg( args[n], XtNborderWidth, &popupBorder ); n++;
  177.  
  178.     XtGetValues( popup, args, n );
  179.  
  180.     dpy       = XtDisplay(popup);
  181.     dpyWidth  = (Position) DisplayWidth ( dpy, DefaultScreen(dpy) );
  182.     dpyHeight = (Position) DisplayHeight( dpy, DefaultScreen(dpy) );
  183.  
  184.     popupX = 
  185.       max( 0,
  186.            min( parentX + ((Position)parentWidth - (Position)popupWidth) / 2,
  187.                 dpyWidth - (Position)popupWidth - 2 * (Position)popupBorder 
  188.          ));
  189.  
  190.     popupY = 
  191.       max( 0,
  192.            min( parentY + ((Position)parentHeight - (Position)popupHeight) / 2,
  193.                 dpyHeight - (Position)popupHeight - 2 * (Position)popupBorder 
  194.           ));
  195.  
  196.     n = 0;
  197.     XtSetArg( args[n], XtNx, popupX); n++;
  198.     XtSetArg( args[n], XtNy, popupY); n++;
  199.  
  200.     XtSetValues( popup, args, n );
  201. }
  202.  
  203. /*--------------------------------------------------------------------------*/
  204. /*
  205.                 P o p u p
  206.  
  207.     Position a shell relative to parent then pop it up.
  208. */
  209. /*--------------------------------------------------------------------------*/
  210. static void Popup( popup, grab )
  211.     Widget    popup;
  212.     XtGrabKind    grab;
  213. {
  214.     /* position shell relative to parent */
  215.     PositionPopup( popup );
  216.  
  217. #ifndef USE_ATHENA
  218.     XtManageChild(popup);
  219. #else
  220.     XtPopup( popup, grab );
  221. #endif
  222. }
  223.  
  224.  
  225.  
  226. /*--------------------------------------------------------------------------*/
  227. /*
  228.                 P o p d o w n 
  229.  
  230.     A callback to popdown a given shell.
  231. */
  232. /*--------------------------------------------------------------------------*/
  233. /* ARGSUSED */
  234. static void Popdown( w, client_data, call_data )
  235.     Widget    w;        /* unused */
  236.     XtPointer    client_data;    /* child of shell to popdown */
  237.     XtPointer    call_data;    /* unused */
  238. {
  239. #ifndef USE_ATHENA
  240.     XtUnmanageChild((Widget) client_data);
  241. #else
  242.     XtPopdown( XtParent((Widget) client_data) );
  243. #endif
  244. }
  245.  
  246.  
  247. /*--------------------------------------------------------------------------*/
  248. /*
  249.         P o p u p E x t e n s i o n E d i t o r
  250.  
  251.     Popup the xpm extension editor form using the given name
  252.     and text.
  253. */
  254. /*--------------------------------------------------------------------------*/
  255. static void PopupExtensionEditor( formW, name, text )
  256.     Widget    formW;
  257.     String    name;
  258.     String    text;
  259. {
  260.     Widget    textW = XtNameToWidget( formW, "*text" );
  261.     Widget    nameW = XtNameToWidget( formW, "name" );
  262.     Arg        args[1];
  263. #ifndef USE_ATHENA
  264.     XmString xmstr;
  265.     
  266.     XmTextSetString(textW, text);
  267.  
  268.     xmstr = XmStringCreateLtoR(name, XmSTRING_DEFAULT_CHARSET);
  269.     XtSetArg(args[0], XmNlabelString, xmstr);
  270.     XtSetValues( nameW, args, 1 );
  271.     XmStringFree(xmstr);
  272.     
  273.     Popup(formW, XtGrabExclusive);
  274. #else
  275.     XtSetArg( args[0], XtNstring, text );
  276.     XtSetValues( textW, args, 1 );
  277.  
  278.     XtSetArg( args[0], XtNlabel, name );
  279.     XtSetValues( nameW, args, 1 );
  280.     Popup( XtParent(formW), XtGrabExclusive );
  281. #endif
  282. }
  283.  
  284.  
  285. /*--------------------------------------------------------------------------*/
  286. /*
  287.             D o E d i t E x t e n s i o n
  288.  
  289.     Given an xpm extension name, get the extension text from the 
  290.     pixmap widget and popup it up in a form for the user to change.
  291. */
  292. /*--------------------------------------------------------------------------*/
  293. void DoEditExtension( name )
  294.     String name; 
  295. {
  296.  
  297.     if ( name != NULL && strcmp(name, "") != 0 ) {
  298.  
  299.         XpmExtension *ext = PWFindExtension( pixmap_widget, name );
  300.  
  301.         String text;
  302.         if ( ext == NULL || ext->nlines == 0 ) 
  303.             text = "";
  304.         else
  305.             text = XpmExtensionToString( ext );
  306.  
  307.         PopupExtensionEditor( extensionEditor, name, text );
  308.     }
  309. }
  310.  
  311. /*--------------------------------------------------------------------------*/
  312. /*
  313.                       A d d T o E x t e n s i o n M e n u
  314.       Add given name to extension menu.
  315. */
  316.  
  317. void AddToExtensionMenu (name)
  318.     char *name;
  319. {
  320.     void ExtensionMenuCallback();
  321. #ifndef USE_ATHENA
  322.     Widget item = XmCreatePushButtonGadget(extensionMenu_widget,
  323.                        name, NULL, 0);
  324.     XtManageChild(item);
  325.     XtAddCallback(item, XmNactivateCallback,
  326.           ExtensionMenuCallback, (XtPointer) NULL );
  327. #else
  328.     Widget item = XtCreateManagedWidget(name,
  329.                     smeBSBObjectClass,
  330.                     extensionMenu_widget,
  331.                     NULL, 0 );
  332.     XtAddCallback(item, XtNcallback, ExtensionMenuCallback,
  333.           (XtPointer) NULL );
  334. #endif
  335. }
  336. /*--------------------------------------------------------------------------*/
  337.  
  338.  
  339. /*--------------------------------------------------------------------------*/
  340. /*
  341.             D o A d d E x t e n s i o n
  342.  
  343.     Prompt user for name of new xpm extension then popup the editor
  344.     for the user to supply the text for the extension.
  345. */
  346. /*--------------------------------------------------------------------------*/
  347. void DoAddExtension()
  348. {
  349.     char *name = NULL;
  350.  
  351.     if ( PopupDialog( input_dialog, 
  352.                       "Add extension name:", 
  353.                       "", &name,
  354.                       XtGrabExclusive ) == Okay ) {
  355.  
  356.         if ( name != NULL && strcmp( name, "" ) != 0 ) {
  357.  
  358.             /* add to menu, if necessary */
  359.             if ( ! XtNameToWidget(extensionMenu_widget, name) )
  360.         AddToExtensionMenu (name);
  361.  
  362.             PWAddExtension( pixmap_widget, name );  /* add, if necessary */
  363.  
  364.             DoEditExtension( name );
  365.         }
  366.     }
  367. }
  368. /*--------------------------------------------------------------------------*/
  369. /*
  370.                       F i x E x t e n s i o n M e n u
  371.         The list of extensions in a pixmap widget has been changed.
  372.         Update the extension menu by destroying the old menu and
  373.         recreating it from scratch.
  374. */
  375. /*--------------------------------------------------------------------------*/
  376. ExtensionNotifyProc FixExtensionMenu (w)
  377.     Widget w;
  378. {
  379.     void ExtensionMenuCallback();
  380.  
  381.     char **PWGetExtensionNames();
  382.     char **names;
  383.     char **name;
  384.     Widget *children;
  385.     Cardinal num_children, i;
  386.     Arg arglist[2];
  387.     
  388. #ifndef USE_ATHENA
  389.     XtSetArg(arglist[0], XmNchildren, &children);
  390.     XtSetArg(arglist[1], XmNnumChildren, &num_children);
  391. #else
  392.     XtSetArg(arglist[0], XtNchildren, &children);
  393.     XtSetArg(arglist[1], XtNnumChildren, &num_children);
  394. #endif
  395.     XtGetValues(extensionMenu_widget, arglist, 2);
  396.     
  397.     /* destroy all children */
  398.     for (i = 0; i < num_children; i++)
  399.       XtDestroyWidget(*(children + i));
  400.     
  401.     /* build again base extension menu */
  402.     MakeMenuPanel(extensionMenu_widget, extension_menu,
  403.           XtNumber(extension_menu), ExtensionMenuCallback);
  404.     
  405.     names = PWGetExtensionNames (w);
  406.     if (names) {
  407.         for (name = names; name && *name; name++) {
  408.            AddToExtensionMenu (*name);
  409.            XtFree (*name);
  410.         }
  411.         if (names)
  412.             XtFree ((char *)names);
  413.     }
  414. }
  415.  
  416.  
  417. /*--------------------------------------------------------------------------*/
  418. /*
  419.             D o R e m o v e E x t e n s i o n
  420.  
  421.     Callback for extension editor form Remove button. Get the name
  422.     of the extension from the form then remove the extension from
  423.     the pixmap widget and from the menu of extension names.
  424. */
  425. /*--------------------------------------------------------------------------*/
  426. void DoRemoveExtension( w, client_data, call_data )
  427.     Widget    w;        /* unused */
  428.     XtPointer    client_data;    /* extension editor form */
  429.     XtPointer    call_data;    /* unused */
  430. {
  431.     Widget       formW = (Widget) client_data;
  432.     Widget       nameW = XtNameToWidget( formW, "name" );
  433.     String       name  = NULL; 
  434.  
  435.     Popdown( NULL, (XtPointer) formW, NULL );
  436.  
  437.     /* get name of extension */
  438. #ifndef USE_ATHENA
  439.     {
  440.     XmString name_xms;
  441.     XtVaGetValues(nameW, XmNlabelString, &name_xms, NULL);
  442.  
  443.     XmStringGetLtoR(name_xms, XmSTRING_DEFAULT_CHARSET, &name);
  444.     }
  445. #else
  446.     XtVaGetValues( nameW, 
  447.                    XtNlabel, &name, 
  448.                    NULL );
  449. #endif
  450.  
  451.     PWRemoveExtension( pixmap_widget, name ); 
  452.  
  453.     /* remove name from menu */
  454.     {
  455.       Widget item = XtNameToWidget(extensionMenu_widget, name);
  456.       XtDestroyWidget( item );
  457.     }
  458. }
  459.  
  460.  
  461. /*--------------------------------------------------------------------------*/
  462. /*
  463.             D o S a v e E x t e n s i o n
  464.  
  465.     Callback for the Okay button of the extension editor form.
  466.     Save the text of the extension with the pixmap widget.
  467. */
  468. /*--------------------------------------------------------------------------*/
  469. void DoSaveExtension( w, client_data, call_data )
  470.     Widget    w;        /* unused */
  471.     XtPointer    client_data;    /* extension editor form */
  472.     XtPointer    call_data;    /* unused */
  473. {
  474.     Widget       formW = (Widget) client_data;
  475.     Widget       nameW = XtNameToWidget( formW, "name" );
  476.     Widget       textW = XtNameToWidget( formW, "*text" );
  477.  
  478.     String       name = NULL; 
  479.     String       text = NULL;
  480.     Arg         args[1];
  481.  
  482.     Popdown( NULL, (XtPointer) formW, NULL );
  483.  
  484. #ifndef USE_ATHENA
  485.     {
  486.     XmString name_xms;
  487.     XtVaGetValues(nameW, XmNlabelString, &name_xms, NULL);
  488.  
  489.     XmStringGetLtoR(name_xms, XmSTRING_DEFAULT_CHARSET, &name);
  490.  
  491.     text = (String) XmTextGetString(textW);
  492.     }
  493.  
  494. #else
  495.     XtVaGetValues( textW, 
  496.                  XtNstring, &text,
  497.                  NULL );
  498.  
  499.     XtVaGetValues( nameW, 
  500.                    XtNlabel, &name,
  501.                    NULL );
  502. #endif
  503.  
  504. /*
  505.     if ( strcmp(text, "") ==  0 ) {
  506.         PWRemoveExtension( pixmap_widget, name );
  507.     }
  508.     else 
  509. */
  510.     {
  511.         XpmExtension *ext = StringToXpmExtension( text );
  512.     ext->name = XtNewString( name );
  513.  
  514.         PWAddExtension( pixmap_widget, name );    /* add if necessary */
  515.         PWUpdateExtension( pixmap_widget, ext );
  516.     }
  517. }
  518.  
  519.  
  520.  
  521. /*--------------------------------------------------------------------------*/
  522. /*
  523.         D o S h o w C u r r e n t E x t e n s i o n s
  524.  
  525.     Print names of xpm extensions in pixmap widget.
  526. */
  527. /*--------------------------------------------------------------------------*/
  528. void DoShowCurrentExtensions()
  529. {
  530.     char **extension_names;
  531.     char **name;
  532.  
  533.     extension_names = PWGetExtensionNames( pixmap_widget );
  534.  
  535.     if ( extension_names != NULL ) {
  536.         fprintf( stderr, "Extension names:\n" );
  537.         for ( name = extension_names; *name != NULL; name++ ) 
  538.             fprintf( stderr, "\t%s\n", *name );
  539.     }
  540. }
  541.  
  542.  
  543.  
  544. /*--------------------------------------------------------------------------*/
  545. /*
  546.         C r e a t e E x t e n s i o n E d i t o r
  547.  
  548.     The xpm extension editor is a form with a label for the extension
  549.     name, and a text box for the extension text.  
  550.  
  551.     Buttons:
  552.     - ok : save text.
  553.     - cancel : ignore any changes made to text.
  554.         - remove : delete extension from pixmap widget and menu.
  555. */
  556. /*--------------------------------------------------------------------------*/
  557. static Widget CreateExtensionEditor( topWidget, editorName )
  558.     Widget    topWidget;    
  559.     String    editorName;
  560. {
  561.     Widget    popup, form, name, text, ok, cancel, remove;
  562.     Position    x, y;
  563.     Dimension    width, height;
  564.     Arg wargs[5];
  565.     Cardinal    n;
  566.  
  567. #ifndef USE_ATHENA
  568.     popup = XmCreateFormDialog(top_widget, editorName, NULL, 0);
  569.     form = popup;
  570.  
  571.     name = XmCreateLabelGadget(form, "name", NULL, 0);
  572.     XtManageChild(name);
  573.  
  574.     text = (Widget) XmCreateScrolledText(form, "text", NULL, 0);
  575.     XtManageChild(text);
  576.  
  577.     ok = XmCreatePushButtonGadget(form, "ok", NULL, 0);
  578.     XtManageChild(ok);
  579.     XtAddCallback(ok, XmNactivateCallback, DoSaveExtension, (XtPointer)form);
  580.  
  581.     cancel = XmCreatePushButtonGadget(form, "cancel", NULL, 0);
  582.     XtManageChild(cancel);
  583.     XtAddCallback(cancel, XmNactivateCallback, Popdown, (XtPointer)form);
  584.  
  585.     remove = XmCreatePushButtonGadget(form, "remove", NULL, 0);
  586.     XtManageChild(remove);
  587.     XtAddCallback(remove, XmNactivateCallback, DoRemoveExtension,
  588.           (XtPointer)form);
  589.  
  590. #else
  591.     popup = XtCreatePopupShell( 
  592.         "extEditorShell", transientShellWidgetClass, 
  593.         top_widget, 
  594.         NULL, 0 );
  595.  
  596.     form = XtCreateManagedWidget( 
  597.         editorName, formWidgetClass, 
  598.         popup,
  599.         NULL, 0 );
  600.  
  601.     name = XtCreateManagedWidget(
  602.         "name", labelWidgetClass, 
  603.         form,
  604.         NULL, 0 );
  605.  
  606.     text = XtCreateManagedWidget(
  607.         "text", asciiTextWidgetClass, 
  608.         form,
  609.         NULL, 0 );
  610.  
  611.     ok = XtCreateManagedWidget(
  612.         "ok", commandWidgetClass, 
  613.         form,
  614.         NULL, 0);
  615.     XtAddCallback( ok, XtNcallback, 
  616.                    DoSaveExtension, (XtPointer) form );
  617.  
  618.     cancel = XtCreateManagedWidget(
  619.         "cancel", commandWidgetClass, 
  620.         form,
  621.         NULL, 0);
  622.     XtAddCallback( cancel, XtNcallback, Popdown, (XtPointer) form );
  623.  
  624.     remove = XtCreateManagedWidget(
  625.         "remove", commandWidgetClass, 
  626.         form,
  627.         NULL, 0);
  628.     XtAddCallback( remove, XtNcallback, DoRemoveExtension, (XtPointer) form );
  629. #endif
  630.  
  631.     return form;
  632. }
  633.  
  634.  
  635. /*--------------------------------------------------------------------------*/
  636. /*
  637.         E x t e n s i o n M e n u C a l l b a c k
  638.  
  639.     Callback for items on the xpm extension menu. Check for adding
  640.     new item to menu, otherwise invoke the extension editor for the
  641.     chosen extension name.
  642. */
  643. /*--------------------------------------------------------------------------*/
  644. void ExtensionMenuCallback(w, client_data, call_data)
  645.      Widget w;
  646.      XtPointer client_data, call_data;
  647. {
  648.     int   *id = (int *)client_data;
  649.  
  650.     if (id && *id == AddExtension)
  651.         DoAddExtension();         /* add then edit */
  652.     else
  653.     DoEditExtension( XtName(w) );
  654. }
  655.  
  656.